/**
 * Captain
 * © 2017 Captain copyright，All rights reserved.
 * http://www.sccaptain.com.cn
 *
 * JAVA : 8
 * 文  件  名: UploadController.java
 * 创  建  人: liutao (liu.tao@sccaptain.com.cn)
 * 创建时间: 2017年8月8日 上午10:11:28
 * 版         本: 1.0.0
 * 备         注:
 * 修订历史:
 */
package com.material.c2c.web.sys.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.cpt.framework.web.JsonResult;
import com.material.c2c.sysconfig.entity.XTPZ_FJ;
import com.material.c2c.util.EncryptUtil;
import com.material.c2c.util.SystemUtil;

/**
 * 文件上传、下载 控制器。
 *
 * @since 1.0
 * @version 1.0
 * @author liutao (liu.tao@sccaptain.com.cn)
 */
@RestController
@RequestMapping("/system/file")
public class FileController {

  private Logger logger = LoggerFactory.getLogger(FileController.class);

  /**
   * 文件上传。
   *
   * @param files
   * @param request
   * @return
   * @throws Exception
   * @since 1.0
   * @version 1.0
   * @author liutao (liu.tao@sccaptain.com.cn)
   */
  @RequestMapping(value = "/upload", method = RequestMethod.POST)
  public JsonResult upload(@RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request)
      throws Exception {
    if (StringUtils.isEmpty(files)) {
      return JsonResult.failed("附件为空！");
    }
    // 临时存储文件根路径 并创建存储路径
    String rootPath = getRootPath();
    LocalDate now = LocalDate.now();
    int year = now.getYear();
    int month = now.getMonthValue();
    // 创建存储目录
    String savePath = getTmpDir(rootPath, year, month);
    createTmpDir(savePath);

    // 开始文件上传
    CommonsMultipartFile file = null;
    String fileName = null;
    String md5 = null;
    String sha1 = null;
    String saveFileName = null;

    List<XTPZ_FJ> fjs = new ArrayList<>();
    XTPZ_FJ fj = null;
    for (int i = 0; i < files.length; i++) {
      file = files[i];
      // 文件上传
      if (!file.isEmpty()) {
        fileName = file.getOriginalFilename();
        String mime = file.getContentType(), suffix = fileName.substring(fileName.lastIndexOf('.'));
        // 加密
        InputStream inputStream = file.getInputStream();
        md5 = EncryptUtil.md5(inputStream);
        sha1 = EncryptUtil.sha1(inputStream);
        saveFileName = md5 + "_" + new Date().getTime() + suffix;

        // 文件上传
        uploadFile(file, savePath, saveFileName);
        // 初始化附件信息。
        fj = new XTPZ_FJ();
        fj.setMd5(md5);
        fj.setSha1(sha1);
        fj.setDx(new Long(file.getSize()).intValue());
        fj.setMime(mime);
        fj.setMc(fileName);
        fj.setWjlj(getStorageDir(year, month, saveFileName));
        fjs.add(fj);
      }
    }
    return JsonResult.success(fjs);
  }

  /**
   * 附件下载
   * @param path
   * @param mime
   * @param fileName
   * @param response
   * @since 1.0
   * @version 1.0
   * @author liutao (liu.tao@sccaptain.com.cn)
   */
  @RequestMapping(value = "/download", method = RequestMethod.GET)
  public void download(@RequestParam(required = true) String path, @RequestParam(required = false) String mime,
                       @RequestParam(required = false) String fileName, HttpServletResponse response) {
    String rootPath = getRootPath();
    String filePath = rootPath + path;
    File file = new File(filePath);
    // 判断文件是否存在
    if (file.exists()) {
      if (!StringUtils.hasText(fileName)) {
        fileName = file.getName();
      }
      // 下载/预览设置
      setResponse(response, mime, fileName);
      download(file, response);
    }
  }

  /**
   * 图件预览
   * @param path
   * @param response
   */
  @RequestMapping(value = "/tj", method = RequestMethod.GET)
  public void tj(@RequestParam String qxdm, @RequestParam String path, HttpServletResponse response) {
    String rootFolder = SystemUtil.PRESENT_PATH, separator = SystemUtil.SEPARATOR,
      attachmentPath = SystemUtil.getAttachmentPath(), tjMime = "image/jpeg",
      rootPath = attachmentPath + separator + rootFolder + separator + qxdm;
    File target = new File(rootPath + separator + path);
    if (target.exists()) {
      setResponse(response, tjMime, target.getName());
      download(target, response);
    }
  }

  private String getTmpDir(String rootPath, int year, int month) {
    return rootPath + SystemUtil.SEPARATOR + SystemUtil.DOCUMENT_TEMP_PATH + SystemUtil.SEPARATOR + year + SystemUtil.SEPARATOR + month;
  }

  private void createTmpDir(String savePath){
    File saveFile = new File(savePath);
    if (!saveFile.exists()) {
      saveFile.mkdirs();
    }
  }

  private String getStorageDir(int year, int month, String saveFileName) {
    return SystemUtil.SEPARATOR + SystemUtil.DOCUMENT_TEMP_PATH + SystemUtil.SEPARATOR + year
      + SystemUtil.SEPARATOR + month + SystemUtil.SEPARATOR + saveFileName;
  }

  private void uploadFile(CommonsMultipartFile file, String savePath, String saveFileName) throws Exception {
    // 文件上传
    FileOutputStream out = null;
    InputStream in = null;
    try {
      // 文件输出流 同时重命名上传的文件
      out = new FileOutputStream(savePath + File.separator + saveFileName);
      // //上传文件的输入流
      in = (InputStream) file.getInputStream();
      // 读写文件流
      byte buffer[] = new byte[4096];
      int count = 0;
      while ((count = in.read(buffer)) != -1) {
        out.write(buffer, 0, count);
      }
    } catch (FileNotFoundException e) {
      logger.error("上传附件,文件“" + file.getOriginalFilename() + "”未找到！", e);
      throw e;
    } catch (IOException e) {
      logger.error("上传附件出错;", e);
      throw e;
    } finally {
      // 释放资源
      close(out, in);
    }
  }

  private void close(FileOutputStream out, InputStream in) throws IOException {
    // 释放资源。
    if (!StringUtils.isEmpty(out)) {
      try {
        out.flush();
        out.close();
      } catch (IOException e) {
        logger.error("附件上传失败,释放资源失败;", e);
        throw e;
      }
    }
    if (!StringUtils.isEmpty(in)) {
      try {
        in.close();
      } catch (IOException e) {
        logger.error("附件上传失败,释放资源失败;", e);
        throw e;
      }
    }
  }

  private void download(File file, HttpServletResponse response) {
    byte[] buffer = new byte[1024];
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    try {
      fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis);
      OutputStream os = response.getOutputStream();
      int i = bis.read(buffer);
      while (i != -1) {
        os.write(buffer, 0, i);
        i = bis.read(buffer);
      }
    } catch (Exception e) {
      throw new RuntimeException("下载文件出错", e);
    } finally {
      close(fis, bis);
    }
  }

  private void setResponse(HttpServletResponse response, String mime, String fileName) {
    if (StringUtils.hasText(mime)) {
      response.setContentType(mime);
      response.addHeader("Content-Disposition", "attachment;fileName=\"" + fileName + "\"");
    } else {
      response.setContentType("application/force-download;charset=UTF-8");// 设置强制下载不打开
      response.addHeader("Content-Disposition", "attachment;fileName=\"" + fileName + "\"");
    }
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setDateHeader("Expires", 0);
  }

  private void close(FileInputStream fis, BufferedInputStream bis) {
    if (!StringUtils.isEmpty(bis)) {
      try {
        bis.close();
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    if (!StringUtils.isEmpty(fis)) {
      try {
        fis.close();
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  private String getRootPath() {
    return SystemUtil.getAttachmentPath();
  }
}
